// Copyright (c) Microsoft Corporation.  All rights reserved.
#include "StdAfx.h"
#include "SideShowService.h"
#include "resource.h"
#include "DPWSSideShowDeviceSimulatorDlg.h"


CSideShowService::CSideShowService(CDPWSSideShowDeviceSimulatorDlg* pMainWnd)
{
    m_cRef = 1;

    m_pMainWnd = pMainWnd;
}

CSideShowService::~CSideShowService(void)
{
}

//------------------------------------------------------------------------------
// CSideShowService::QueryInterface
//------------------------------------------------------------------------------
HRESULT CSideShowService::QueryInterface(
                                        REFIID riid, 
                                        void** ppvObject
                                        )
{
    HRESULT hr = S_OK;

    if( NULL == ppvObject )
    {
        return E_INVALIDARG;
    }

    *ppvObject = NULL;

    if( __uuidof(ISideShowServiceType) == riid )
    {
        *ppvObject = static_cast<ISideShowServiceType*>(this);
        AddRef();
    }
    else if( __uuidof(IUnknown) == riid )
    {
        *ppvObject = static_cast<IUnknown*>(this);
        AddRef();
    }
    else
    {
        hr = E_NOINTERFACE;
    }

    return hr;
}

//------------------------------------------------------------------------------
// CSideShowService::AddRef
//------------------------------------------------------------------------------
ULONG CSideShowService::AddRef()
{
    return InterlockedIncrement( &m_cRef );
}

//------------------------------------------------------------------------------
// CControlService::Release
//------------------------------------------------------------------------------
ULONG CSideShowService::Release()
{
    LONG lRef = InterlockedDecrement( &m_cRef );

    if( 0 == lRef )
    {
        delete this;
    }

    return lRef;
}

//------------------------------------------------------------------------------
// CSideShowService::GetSideShowElements
//      Return properties of Windows SideShow display area to DPWS client
//------------------------------------------------------------------------------
HRESULT CSideShowService::GetSideShowElements
(   /*[out]*/ SIDE_SHOW_ELEMENTS_TYPE** SideShowElementsOut
 )
{
     if (!SideShowElementsOut)
     {
          return E_POINTER;
     }

     // allocate memory for output parameter
     *SideShowElementsOut = (SIDE_SHOW_ELEMENTS_TYPE*) ::WSDAllocateLinkedMemory(NULL, sizeof(SIDE_SHOW_ELEMENTS_TYPE));

     CSideShowDisplayFormat format(0, 0, 0);
     m_pMainWnd->GetSideShowDisplayFormat(format);

    (*SideShowElementsOut)->Any = NULL;
    (*SideShowElementsOut)->ColorDepth = format.m_depth;
    (*SideShowElementsOut)->DPI = 96;
    (*SideShowElementsOut)->FullScreenSideShow = 0;

    (*SideShowElementsOut)->SideShowAreaWidth = format.m_width;
    (*SideShowElementsOut)->SideShowAreaHeight = format.m_height;

    return S_OK;
}

//------------------------------------------------------------------------------
// CSideShowService::SendSideShowFrameStream
//      Receive SideShow picture data from DPWS client
//------------------------------------------------------------------------------
HRESULT CSideShowService::SendSideShowFrameStream
(   /*[in]*/ SIDE_SHOW_FRAME_STREAM_TYPE* SideShowStreamInformation
 )
{
    // Obtain the inbound attachment interface
    IWSDAttachment* pSideShowData =  (IWSDAttachment*) SideShowStreamInformation->FrameStream;
    IWSDInboundAttachment* pInboundAttachment = NULL;
    HRESULT hr = pSideShowData->QueryInterface( __uuidof(IWSDInboundAttachment), 
        (void**)&pInboundAttachment);

    if (FAILED(hr))
    {
        return E_FAIL;
    }

    ULONG bufSize = 0;
    BYTE* pBuf = 0;

    // CSideShowDlg* pSideshowWnd = m_pMainWnd->GetSideShowWnd();
    m_pMainWnd->GetFrameBuffer(&pBuf, &bufSize);

    if (!pBuf)
        return E_FAIL;

    // read SideShow data...
    BYTE* pRead = pBuf;
    ULONG left = bufSize;
    ULONG readSize = 0;

    while( S_OK == hr )
    {
        hr = pInboundAttachment->Read(pRead, left, &readSize );

        pRead += readSize;
        left -= readSize;
        
        // If that was the last read, reset hr and bail out
        if (S_OK != hr || 0 == left )
        {
            break;
        }
    }

    pInboundAttachment->Release();
//#if 0
     if (m_pMainWnd)
     {
          // temporarily support only one client
          m_pMainWnd->SetClientID(SideShowStreamInformation->ClientID);
          if (m_pMainWnd->GetClientID() == SideShowStreamInformation->ClientID)
               m_pMainWnd->PostMessage(WM_SIDESHOW_UPDATE, 0, 0);
     }
//#endif

    return S_OK;
}